package com.example.btchat.client;

import java.io.IOException;
import java.io.OutputStream;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.example.btchat.BTChat;
import com.example.btchat.Message;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.TextView.OnEditorActionListener;

public class MainActivity extends Activity
{
	private static final int REQUEST_ENABLE_BT = 1;
	private static final int REQUEST_SELECT_DEVICE = 2;
	
	private BluetoothAdapter adapter;
	private JSONArray messages;
	private ReaderThread readerThread = null;
	private BluetoothSocket socket = null;
	private LinearLayout viewMessages;
	private EditText viewNewMessage;
	
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		messages = new JSONArray();
		
		viewMessages = (LinearLayout) findViewById(R.id.messages);
		viewNewMessage = (EditText) findViewById(R.id.newmessage);
		
		adapter = BluetoothAdapter.getDefaultAdapter();
		
		if(adapter == null)
		{
			Toast.makeText(this, getString(R.string.msg_no_bluetooth), Toast.LENGTH_LONG).show();
			finish();
			return;
		}
		
		if(adapter.isEnabled())
		{
			Intent intent = new Intent(this, SelectDevice.class);
			startActivityForResult(intent, REQUEST_SELECT_DEVICE);
		}
		else
		{
			Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(intent, REQUEST_ENABLE_BT);
		}
		
		viewNewMessage.setOnEditorActionListener(new OnEditorActionListener()
		{
			@Override
			public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
			{
				boolean handled = false;
				if(actionId == EditorInfo.IME_ACTION_SEND)
				{
					sendMessage();
					handled = true;
				}
				return handled;
			}
		});
	}
	
	public void onMessageReceived(Message msg)
	{
		messages.put(msg);
		
		addMessage(msg);
	}
	
	public void onReadError()
	{
		try
		{
			socket.getInputStream().close();
		}
		catch(IOException e1)
		{}
		
		try
		{
			socket.getOutputStream().close();
		}
		catch(IOException e)
		{}
		
		try
		{
			socket.close();
		}
		catch(IOException e)
		{}
		
		socket = null;
		onSocketError();
	}
	
	private void addMessage(Message msg)
	{
		TextView tv = new TextView(this);
		tv.setText(Html.fromHtml("<strong>" + msg.getSource() + "</strong>: "));
		tv.append(msg.getMessage());
		
		viewMessages.addView(tv);
	}
	
	private void connectServer(String address)
	{
		BluetoothDevice device = adapter.getRemoteDevice(address);
		try
		{
			socket = device.createRfcommSocketToServiceRecord(BTChat.MY_UUID);
			socket.connect();
		}
		catch(IOException e)
		{
			onSocketError();
			return;
		}
		
		try
		{
			readerThread = new ReaderThread(this, socket);
		}
		catch(IOException e)
		{
			onReadError();
		}
		readerThread.run();
	}
	
	private void onSocketError()
	{
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		
		builder.setTitle(R.string.dialog_connect_title);
		builder.setMessage(R.string.dialog_connect_message);
		builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener()
		{
			public void onClick(DialogInterface dialog, int id)
			{
				Intent intent = new Intent(MainActivity.this, SelectDevice.class);
				startActivityForResult(intent, REQUEST_SELECT_DEVICE);
				return;
			}
		});
		builder.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener()
		{
			public void onClick(DialogInterface dialog, int id)
			{
				dialog.cancel();
			}
		});
		
		AlertDialog dialog = builder.create();
		dialog.setCancelable(true);
		dialog.setOnCancelListener(new OnCancelListener()
		{
			@Override
			public void onCancel(DialogInterface dialog)
			{
				finish();
				return;
			}
		});
		
		dialog.show();
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		if(requestCode == REQUEST_ENABLE_BT)
		{
			if(resultCode == RESULT_OK)
			{
				Intent intent = new Intent(this, SelectDevice.class);
				startActivityForResult(intent, REQUEST_SELECT_DEVICE);
				return;
			}
			else
			{
				Toast.makeText(this, getString(R.string.msg_bluetooth_not_active), Toast.LENGTH_LONG)
					.show();
				finish();
				return;
			}
		}
		
		if(requestCode == REQUEST_SELECT_DEVICE && resultCode == RESULT_OK)
		{
			String address = data.getStringExtra("device");
			connectServer(address);
		}
	}
	
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState)
	{
		super.onRestoreInstanceState(savedInstanceState);
		
		if(savedInstanceState == null)
			return;
		
		String data = savedInstanceState.getString("messages");
		if(data == null)
			return;
		
		try
		{
			messages = new JSONArray(data);
		}
		catch(JSONException e)
		{
			return;
		}
		
		viewMessages.removeAllViews();
		for(int i = 0; i < messages.length(); i++)
		{
			try
			{
				String str = messages.getString(i);
				Message msg = Message.fromString(str);
				addMessage(msg);
			}
			catch(JSONException e)
			{}
		}
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		super.onSaveInstanceState(outState);
		
		outState.putString("messages", messages.toString());
	}
	
	protected void sendMessage()
	{
		final JSONObject obj = new JSONObject();
		try
		{
			obj.put("msg", viewNewMessage.getText());
			obj.put("source", adapter.getName());
		}
		catch(JSONException e1)
		{
			Toast.makeText(this, R.string.error_on_sent, Toast.LENGTH_SHORT).show();
			return;
		}
		
		try
		{
			OutputStream output = socket.getOutputStream();
			output.write(obj.toString().getBytes());
		}
		catch(IOException e)
		{
			Toast.makeText(this, R.string.error_on_sent, Toast.LENGTH_SHORT).show();
			return;
		}
		
		viewNewMessage.setText("");
	}
}
